/*
 * v1.1 by tonydon site:txdnet.cn
 * netbeansIDE 7.1
 */
package cn.txdnet.txweb.model;

import cn.txdnet.txweb.utils.JsonUtil;
import cn.txdnet.txweb.utils.VelocityUtil;
import cn.txdnet.txweb.utils.WebUtil;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import txdnet.util.DataUtil;
import txdnet.util.Logger;
import txdnet.util.StaticMark;

/**
 * @see 模型数据处理者
 * @author txdnet
 */
public final class ModelHandler {

    public static String JSP_VIEW_DIR = "/jsp";
    public static final String JSP_EXT = "jsp";

    /*
     * @see数据层到视图层的处理
     */
    public static void processor(Object model, HttpServletRequest req,
            HttpServletResponse res, String urlaction) throws Exception {
        if (model instanceof TxtModel) {  // 如果是TxtModel实例
            doTxtModelHandler((TxtModel) model, res);

        } else if (model instanceof PageModel) {  // 如果是PageModel实例
            doPageModelHandler((PageModel) model, req, res);

        } else if (model instanceof JspModel) { // jsp MODEL 实例
            doJspModelHandler((JspModel) model, req, res, urlaction);

        } else if (model instanceof DownModel) { // 下载模型处理
            doDownModelHandler((DownModel) model, res);
        }
    }

    /*
     * @see 处理文本类输出数据模型
     */
    private static void doTxtModelHandler(TxtModel model, HttpServletResponse res)
            throws Exception {
        ViewType type = model.getType();
        Object content = model.getContent();
        if (content == null) {
            return;
        }
        if (type == ViewType.TXT_MODEL_TEXT) {
            res.setContentType("text/plain");
            res.getWriter().print(content);

        } else if (type == ViewType.TXT_MODEL_JSON) {
            res.setContentType("application/json");
            // 注意输出JSON KEYNAME的大小写需求,更换toJSONString即可
            res.getWriter().print(JsonUtil.toJSONString(content));

        } else if (type == ViewType.TXT_MODEL_JS) {
            res.setContentType("application/javascript");
            res.getWriter().print(content);

        } else if (type == ViewType.TXT_MODEL_HTML) {
            res.setContentType("text/html");
            res.getWriter().print(content);
        }
    }

    /*
     * @see 处理页面类数据模型
     */
    private static void doPageModelHandler(PageModel model, HttpServletRequest req,
            HttpServletResponse res) throws Exception {
        ViewType type = model.getType();
        String page = model.getPage();
        if (page == null) {
            return;
        }
        if (type == ViewType.PAGE_MODEL_REDIRECT) {
            res.sendRedirect(page);

        } else if (type == ViewType.PAGE_MODEL_FORWARD) {
            if (model.getModel() != null) {
                req.setAttribute(model.getName(), model.getModel());
            }
            req.getRequestDispatcher(page).forward(req, res);

        } else if (type == ViewType.PAGE_MODEL_VELOCITY) {
            res.setContentType("text/html");
            Map<String, Object> dataMap = (Map<String, Object>) model.getModel();
            if (dataMap == null) {
                dataMap = new HashMap<String, Object>(3);
            }
            dataMap.put("req", req);
            dataMap.put("res", res);
            dataMap.put("ctxpath", WebUtil.WEB_CTX_PATH);
            res.getWriter().print(
                    VelocityUtil.mergeTemplateToString(
                    page.concat(VelocityUtil.VM_EXT), dataMap, StaticMark.ENCODING_UTF8));

        }
    }

    /**
     * 处理JSP model请求
     *
     * @param model
     * @param req
     * @param res
     * @param urlaction
     * @throws Exception
     */
    private static void doJspModelHandler(JspModel model, HttpServletRequest req,
            HttpServletResponse res, String urlaction) throws Exception {
        ViewType type = model.getType();
        String page = model.getPage();
        if (page == null) {
            return;
        }
        if (type == ViewType.PAGE_MODEL_JSP) {
            if (model.getModel() != null) {
                req.setAttribute(model.getName(), model.getModel());
            }
            req.setAttribute("ctxpath", WebUtil.WEB_CTX_PATH);
            req.getRequestDispatcher(new StringBuilder(JSP_VIEW_DIR).append(urlaction)
                    .append(StaticMark.CHAR_SLASH)
                    .append(page)
                    .append(StaticMark.CHAR_DOT)
                    .append(JSP_EXT).toString()).forward(req, res);
        }
    }

    /**
     * 处理下载model请求
     *
     * @param model
     * @param res
     * @throws Exception
     */
    private static void doDownModelHandler(DownModel model, HttpServletResponse res) throws Exception {
        ViewType type = model.getType();
        if (DataUtil.isEmpty(model.getName())) {
            return;
        }

        // 中文文件下载乱码解决
        String fn = new String(model.getName().getBytes(StaticMark.ENCODING_GBK), "ISO-8859-1");
        res.reset();
        res.setContentType("application/octet-stream; charset=GBK");
        res.setCharacterEncoding(StaticMark.ENCODING_GBK);
        res.setHeader("Content-Disposition", "attachment;filename=".concat(fn));

        if (type == ViewType.DOWN_MODEL_PLAIN) {
            if (DataUtil.isEmpty(model.getText())) {
                return;
            }
            res.getWriter().write(model.getText());

        } else if (type == ViewType.DOWN_MODEL_STREAM) {
            if (model.getFileInputStream() == null) {
                return;
            }
            OutputStream os = null;
            InputStream is = null;
            try {
                os = res.getOutputStream();
                is = model.getFileInputStream();
                IOUtils.copyLarge(is, os);
                os.flush();
                os.close();
            } catch (Exception e) {
                Logger.error(ModelHandler.class, e);
            } finally {
                if (is != null) {
                    IOUtils.closeQuietly(is);
                }
                if (os != null) {
                    IOUtils.closeQuietly(os);
                }
            }

        }
    }
}
